home *** CD-ROM | disk | FTP | other *** search
INI File | 1992-08-19 | 12.3 KB | 309 lines |
- [LISTING ONE]
-
- ////////////////////////////////////////////////////////////////////////////
- // UNLOAD.C Copyright (c) 1992 by Mike Sax
- // Unload is a small programmer's utility that lets you remove any program
- // or DLL that is stuck in memory.
- ////////////////////////////////////////////////////////////////////////////
- #define STRICT 1
- #include <windows.h>
- #include <string.h>
- #include <toolhelp.h>
- #include "unload.h"
-
- // Global variables:
- static HINSTANCE ghInstance;
-
- // Exported functions:
- BOOL FAR PASCAL _export MainDlgProc(HWND hDlg, unsigned message, WORD wParam,
- LONG lParam);
- BOOL FAR PASCAL _export WarningDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
- LONG lParam);
- BOOL FAR PASCAL _export EnumTaskWindowsFunc(HWND hWnd, DWORD lParam);
-
- // Internal functions:
- void static FillupComboBox(HANDLE hComboBox);
- void static ShowItemInfo(HWND hDlg, HWND hComboBox);
- void static KillTask(HTASK hTask, int nMethod);
- BOOL static IsDLL(HMODULE hModule);
-
- // The WinMain function is called at the beginning of our program
- int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow)
- {
- ghInstance = hInstance;
- (void)lpCmdLine;
- if (!hPrevInstance)
- {
- WNDCLASS wc;
- // Register private dialog class
- wc.style = 0l;
- wc.lpfnWndProc = DefDlgProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = DLGWINDOWEXTRA;
- wc.hInstance = ghInstance;
- wc.hIcon = LoadIcon(hInstance, "Unload");
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "Unload";
- if (!RegisterClass(&wc))
- return -1;
- }
- // Use a dialog box as our main window and pass the nCmdShow parameter
- // in lParam of MainDlgProc's WM_INITDIALOG.
- return DialogBoxParam(ghInstance, "Unload", NULL, (DLGPROC)
- MakeProcInstance((FARPROC)MainDlgProc, ghInstance),
- (LONG)nCmdShow);
- // Proc Instance will be automatically cleaned up by Windows.
- }
- // MainDlgProc handles all messages for our main window.
- BOOL FAR PASCAL _export MainDlgProc(HWND hDlg, unsigned message, WORD wParam,
- LONG lParam)
- {
- switch (message)
- {
- case WM_INITDIALOG:
- // We passed the nCmdShow parameter of WinMain in lParam
- ShowWindow(hDlg, LOWORD(lParam));
- break;
- case WM_CLOSE:
- EndDialog(hDlg, FALSE);
- break;
- case WM_COMMAND:
- switch(wParam)
- {
- // Combobox notification message
- case IDD_COMBOBOX:
- if (HIWORD(lParam) == CBN_DROPDOWN)
- FillupComboBox((HANDLE)LOWORD(lParam));
- else if (HIWORD(lParam) == CBN_SELCHANGE)
- {
- static BOOL bFirst = TRUE;
- if (bFirst)
- {
- SetDlgItemText(hDlg, IDD_MESSAGE, "Compuserve: 75470,1403");
- bFirst = FALSE;
- }
- ShowItemInfo(hDlg, (HANDLE)LOWORD(lParam));
- }
- break;
- // User pressed the "Unload" button
- case IDD_UNLOAD:
- {
- FARPROC lpProc;
- int nCurSel = (int)SendDlgItemMessage(hDlg, IDD_COMBOBOX,
- CB_GETCURSEL, 0, 0l);
- // If no item selected, do nothing
- if (nCurSel == CB_ERR)
- {
- MessageBeep(0);
- break;
- }
- lpProc = MakeProcInstance((FARPROC)WarningDlgProc,
- ghInstance);
- // Call "Unload" dialog box and pass the module handle
- // in lParam of WarningDlgProc's WM_INITDIALOG
- if (DialogBoxParam(ghInstance, "WARNING", hDlg,
- (DLGPROC)lpProc, SendDlgItemMessage(hDlg,
- IDD_COMBOBOX, CB_GETITEMDATA, nCurSel, 0l)))
- {
- // Give Windows a chance to process the WM_QUIT
- // or WM_CLOSE messages we might have posted
- Yield();
- FillupComboBox(GetDlgItem(hDlg, IDD_COMBOBOX));
- }
- FreeProcInstance(lpProc);
- }
- }
- break;
- default:
- return FALSE; // We did not process the message
- }
- return TRUE; // We processed the message
- }
- // FillupComboBox fills up the combo box with a list of all modules
- // that are currently loaded. Every item in the list box also contains
- // a "long" data item (attached using CB_SETITEMDATA) that is a combination
- // of the module handle and the usage count.
- void static FillupComboBox(HANDLE hComboBox)
- {
- int nIndex;
- BOOL bSucces;
- HMODULE hSelectedModule;
- MODULEENTRY ModuleEntry;
- // Keep the module handle of the item that is currently selected
- nIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0l);
- hSelectedModule = (HMODULE) ((CB_ERR == nIndex) ? -1 :
- HIWORD(SendMessage(hComboBox, CB_GETITEMDATA, nIndex, 0l)));
- SendMessage(hComboBox, CB_RESETCONTENT, 0, 0l);
- ModuleEntry.dwSize = sizeof (MODULEENTRY);
- bSucces = ModuleFirst(&ModuleEntry);
- while(bSucces)
- {
- if (IsDLL(ModuleEntry.hModule))
- AnsiLower(ModuleEntry.szModule);
- nIndex = (int)SendMessage(hComboBox, CB_ADDSTRING, 0,
- (LONG) (LPSTR) ModuleEntry.szModule);
- if ((nIndex != CB_ERR) && (nIndex != CB_ERRSPACE))
- {
- SendMessage(hComboBox, CB_SETITEMDATA, nIndex,
- MAKELONG(ModuleEntry.wcUsage, ModuleEntry.hModule));
- bSucces = ModuleNext(&ModuleEntry);
- }
- else
- bSucces = FALSE;
- }
- // Check if the previously selected module is still in the list and
- // if so, reselect it.
- for (nIndex = SendMessage(hComboBox, CB_GETCOUNT, 0, 0l) - 1;
- nIndex >= 0 ; --nIndex)
- if ((HMODULE) HIWORD(SendMessage(hComboBox, CB_GETITEMDATA,
- nIndex, 0)) == hSelectedModule)
- {
- SendMessage(hComboBox, CB_SETCURSEL, nIndex, 0l);
- break;
- }
- ShowItemInfo(GetParent(hComboBox), hComboBox);
- }
- // Show information about the currently selected item in the combobox.
- void static ShowItemInfo(HWND hDlg, HWND hComboBox)
- {
- int nCurSel;
- nCurSel = (int)SendMessage(hComboBox, CB_GETCURSEL, 0, 0l);
- if (CB_ERR == nCurSel)
- {
- SetDlgItemText(hDlg, IDD_FILENAME, "");
- SetDlgItemText(hDlg, IDD_MODULE, "");
- SetDlgItemText(hDlg, IDD_KIND, "");
- SetDlgItemText(hDlg, IDD_USAGE, "");
- EnableWindow(GetDlgItem(hDlg, IDD_UNLOAD), FALSE);
- }
- else
- {
- char szScrap[MAX_PATH + 1];
- char *pcFilename;
- DWORD dwData;
- dwData = SendMessage(hComboBox, CB_GETITEMDATA, nCurSel, 0l);
- GetModuleFileName((HMODULE)HIWORD(dwData), szScrap, MAX_PATH);
- // Remove the path from the filename
- pcFilename = strrchr(szScrap, '\\');
- pcFilename = (pcFilename == NULL) ? szScrap : pcFilename + 1;
- SetDlgItemText(hDlg, IDD_KIND, (IsDLL((HMODULE)HIWORD(dwData)) ?
- "Library" : "Program"));
- SetDlgItemText(hDlg, IDD_FILENAME, pcFilename);
- SetDlgItemInt(hDlg, IDD_USAGE, LOWORD(dwData), FALSE);
- wsprintf(szScrap, "%04x", HIWORD(dwData));
- SetDlgItemText(hDlg, IDD_MODULE, (LPSTR) szScrap);
- EnableWindow(GetDlgItem(hDlg, IDD_UNLOAD), LOWORD(dwData));
- }
- }
- // When the user pressed the Unload button, the "warning dialog" appears
- BOOL FAR PASCAL _export WarningDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
- LONG lParam)
- {
- static HMODULE hModule; // Only one dialog can be active!
- switch(wMessage)
- {
- case WM_INITDIALOG:
- // The handle of the module to be freed is in the hiword of iParam,
- // passed on using DialogBoxParam. Since we use same dialog box for
- // both programs and libraries, we have to adjust our dialog a
- // a little, depending on the type of dialog.
- if (IsDLL((HMODULE)HIWORD(lParam)))
- {
- EnableWindow(GetDlgItem(hDlg, IDD_TERMINATE), FALSE);
- EnableWindow(GetDlgItem(hDlg, IDD_DESTROY), FALSE);
- }
- else
- SetDlgItemText(hDlg, IDD_REFERENCEZERO, "Post WM_QUIT message");
- CheckDlgButton(hDlg, IDD_REFERENCEZERO, 1);
- hModule = (HMODULE)HIWORD(lParam);
- break;
- case WM_COMMAND:
- switch(wParam)
- {
- case IDOK:
- {
- if (IsDLL(hModule))
- {
- int nUsage = GetModuleUsage(hModule);
- while (nUsage--)
- FreeLibrary(hModule);
- }
- else
- {
- BOOL bSucces;
- TASKENTRY TaskEntry;
- int nMethod =
- (IsDlgButtonChecked(hDlg, IDD_REFERENCEZERO)) ? 0 :
- (IsDlgButtonChecked(hDlg, IDD_TERMINATE)) ? 1 : 2;
- TaskEntry.dwSize = sizeof(TASKENTRY);
- bSucces = TaskFirst(&TaskEntry);
- while(bSucces)
- {
- if (TaskEntry.hModule == hModule)
- KillTask(TaskEntry.hTask, nMethod);
- bSucces = TaskNext(&TaskEntry);
- }
- }
- EndDialog(hDlg, TRUE);
- }
- break;
- case IDCANCEL:
- EndDialog(hDlg, FALSE);
- break;
- }
- break;
- case WM_CLOSE:
- EndDialog(hDlg, FALSE);
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- // KillTask kills a task using a method of your choice. It is called
- // from the "Warning" dialog box when the user presses Ok.
- void static KillTask(HTASK hTask, int nMethod)
- {
- switch(nMethod)
- {
- case 0: // Post WM_QUIT message
- PostAppMessage(hTask, WM_QUIT, 0, 0l);
- break;
- case 1: // Terminate application
- TerminateApp(hTask, NO_UAE_BOX);
- break;
- case 2: // Close all the task's windows
- {
- FARPROC lpProc = MakeProcInstance((FARPROC)EnumTaskWindowsFunc,
- ghInstance);
- EnumTaskWindows(hTask,(WNDENUMPROC)lpProc, 0l);
- FreeProcInstance(lpProc);
- }
- break;
- }
- }
- // EnumTaskWindowsFunc is called for every toplevel window that belongs to
- // a task. It simply posts a WM_CLOSE message to this window.
- BOOL FAR PASCAL _export EnumTaskWindowsFunc(HWND hWnd, DWORD lParam)
- {
- (void)lParam; // Avoid compiler warnings
- if (GetParent(hWnd) == NULL)
- PostMessage(hWnd, WM_CLOSE, 0, 0l);
- return TRUE;
- }
- // IsDLL returns TRUE if the specified module is a Dynamic Link Library, or
- // FALSE if it is a program.
- BOOL static IsDLL(HMODULE hModule)
- {
- int i;
- // The module handle is really the selector of a far pointer to
- // the new-style .EXE header of the module. The bit at 0x8000 of
- // the word at offset 0xC in this structure is set if it's a DLL.
- MemoryRead((WORD)hModule, 0xCl, &i, sizeof(i));
- return (i & 0x8000) ? TRUE : FALSE;
- }
-